package model;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;

import javax.swing.BorderFactory;
import javax.swing.JPanel;
import javax.swing.border.BevelBorder;


public class Node extends JPanel implements Comparable<Node>{
	
	public enum NodeState {
		CLOSEDLIST,
		OPENLIST,
		UNKNOWN,
		PATH
		
	}
	
	public enum LastNode{
		NORTH, EAST, SOUTH, WEST,
		NORTHEAST, SOUTHEAST, SOUTHWEST, NORTHWEST, NO
	}
	
	private boolean obstacle = false;
	private boolean isStart = false;
	private boolean isTarget = false;
	
	private int mySize;
	private int x;
	private int y;
	
	private int gCosts;
	private int hCosts;
	private int costs;
	
	private LastNode last;
	
	private NodeState state;
	
	private Node me;
	
	public Node (int x, int y) {
		mySize = PV.getNodeSize();
		//System.out.println(mySize);
		this.x = x;
		this.y = y;
		this.setLocation(x*PV.getNodeSize(), y*PV.getNodeSize());
		
		this.setSize(new Dimension(mySize,mySize));
		this.setVisible(true);
		me = this;
		
		//this.setToolTipText("F:" + getCosts());
		this.setBorder(BorderFactory.createBevelBorder(BevelBorder.LOWERED));
		
		//System.out.println(PV.getKeyListener());
		this.addMouseListener(new MouseListener() {
			
			
			
			@Override
			public void mouseEntered(MouseEvent arg0) {
				PV.setCurrentMouseNodeX(getX());
				PV.setCurrentMouseNodeY(getY());
				FindPath.mainWindow.getLabelFCosts().setText(String.format("%-20s %n %s"," F Costs: ",PV.getNodeNet()[getX()][getY()].getCosts()));
				FindPath.mainWindow.getLabelGCosts().setText(String.format("%-20s %n %s"," G Costs: ",PV.getNodeNet()[getX()][getY()].getgCosts()));
				FindPath.mainWindow.getLabelHCosts().setText(String.format("%-20s %n %s"," H Costs: ",PV.getNodeNet()[getX()][getY()].gethCosts()));
				if(!me.obstacle){
					me.setBorder(BorderFactory.createBevelBorder(BevelBorder.RAISED));
				}else{
					me.setBorder(BorderFactory.createBevelBorder(BevelBorder.LOWERED));
				}
				
				
				
				if(PV.isMousePressed()){
					if(FindPath.mainWindow.getRadioObstacle().isSelected()){
						me.setObstacle(true);
						
					}else if(FindPath.mainWindow.getRadioClear().isSelected()){
						me.setObstacle(false);
					}else if(FindPath.mainWindow.getRadioStart().isSelected()){
						for (int i = 0; i < PV.getNodeNet().length; i++) {
							for (int j = 0; j < PV.getNodeNet()[i].length; j++) {
								if(PV.getNodeNet()[i][j].isStart()){
									PV.getNodeNet()[i][j].setStart(false);
									PV.getNodeNet()[i][j].repaint();
								}
							}
						}
						me.setObstacle(false);
						me.setStart(true);
					}else if(FindPath.mainWindow.getRadioEnd().isSelected()){
						for (int i = 0; i < PV.getNodeNet().length; i++) {
							for (int j = 0; j < PV.getNodeNet()[i].length; j++) {
								if(PV.getNodeNet()[i][j].isTarget()){
									PV.getNodeNet()[i][j].setTarget(false);
									PV.getNodeNet()[i][j].repaint();
								}
							}
						}
						me.setObstacle(false);
						me.setTarget(true);
					}
				}
				
				
				
			}
			
			@Override
			public void mouseClicked(MouseEvent arg0) {
				//System.out.println("test");
				
			}

			@Override
			public void mouseExited(MouseEvent e) {
				if(!me.obstacle){
					me.setBorder(BorderFactory.createBevelBorder(BevelBorder.LOWERED));
				}else{
					me.setBorder(BorderFactory.createBevelBorder(BevelBorder.RAISED));
				}
				
				
			}

			@Override
			public void mousePressed(MouseEvent e) {
				PV.setMousePressed(true);
				if(FindPath.mainWindow.getRadioObstacle().isSelected()){
					me.setObstacle(true);
					me.repaint();
				}else if(FindPath.mainWindow.getRadioClear().isSelected()){
					me.setObstacle(false);
					me.repaint();
				}else if(FindPath.mainWindow.getRadioStart().isSelected()){
					for (int i = 0; i < PV.getNodeNet().length; i++) {
						for (int j = 0; j < PV.getNodeNet()[i].length; j++) {
							if(PV.getNodeNet()[i][j].isStart()){
								PV.getNodeNet()[i][j].setStart(false);
								PV.getNodeNet()[i][j].repaint();
							}
						}
					}
					me.setObstacle(false);
					me.setStart(true);
					me.repaint();
					
				}else if(FindPath.mainWindow.getRadioEnd().isSelected()){
					for (int i = 0; i < PV.getNodeNet().length; i++) {
						for (int j = 0; j < PV.getNodeNet()[i].length; j++) {
							if(PV.getNodeNet()[i][j].isTarget()){
								PV.getNodeNet()[i][j].setTarget(false);
								PV.getNodeNet()[i][j].repaint();
							}
						}
					}
					me.setObstacle(false);
					me.setTarget(true);
					me.repaint();
					
				}
			}

			@Override
			public void mouseReleased(MouseEvent e) {
				PV.setMousePressed(false);
				
			}
		});
		
		state = NodeState.UNKNOWN;
		
	}
	
	@Override
	public void paint(Graphics g) {
		
		//mySize = PV.getNodeSize();
		//this.setLocation(x*PV.getNodeSize(), y*PV.getNodeSize());
		//this.setSize(new Dimension(mySize,mySize));
		
		if (isStart) {
			setBackground(Color.GREEN);
		}else if (isTarget) {
			setBackground(Color.BLUE);
		}else if (obstacle) {
			setBackground(Color.DARK_GRAY);
			setBorder(BorderFactory.createBevelBorder(BevelBorder.RAISED));
		}else{
			switch (state) {
			case CLOSEDLIST:
				setBackground(Color.GRAY);
				break;
			case OPENLIST:
				setBackground(Color.YELLOW);
				break;
			case PATH:
				setBackground(Color.CYAN);
				break;
			case UNKNOWN:
				setBackground(Color.LIGHT_GRAY);
				break;
			default:
				break;
			}
			setBorder(BorderFactory.createBevelBorder(BevelBorder.LOWERED));
		}
		
		
		super.paint(g);
	}
	
	public Node (int x, int y, int gCost){
		this(x,y);
		gCosts = gCost;
	}
	
	public NodeState getState() {
		return state;
	}

	public int getMySize() {
		return mySize;
	}

	public void setMySize(int size) {
		this.mySize = size;
	}

	public int getX() {
		return x;
	}

	public void setX(int x) {
		this.x = x;
	}

	public int getY() {
		return y;
	}

	public void setY(int y) {
		this.y = y;
	}

	public int getgCosts() {
		return gCosts;
	}

	public void setgCosts(int d) {
		this.gCosts = d;
	}

	public int gethCosts() {
		return hCosts;
	}

	public void sethCosts(int hCosts) {
		this.hCosts = hCosts;
	}

	public int getCosts() {
		costs = gCosts + hCosts;
		return costs;
	}

	public void setCosts(int costs) {
		this.costs = costs;
	}

	public void setState(NodeState state) {
		this.state = state;
	}

	public boolean isObstacle() {
		return obstacle;
	}

	public void setObstacle(boolean obstacle) {
		this.obstacle = obstacle;
	}

	@Override
	public int compareTo(Node o) {
		if(this.getCosts() < o.getCosts()){
			return -1;
		} else if(this.getCosts() > o.getCosts()){
			return 1;
		} else{
			return 0;
		}
		
	}

	public boolean isStart() {
		return isStart;
	}

	public void setStart(boolean isStart) {
		this.isStart = isStart;
	}

	public boolean isTarget() {
		return isTarget;
	}

	public void setTarget(boolean isTarget) {
		this.isTarget = isTarget;
	}

	public LastNode getLast() {
		return last;
	}

	public void setLast(LastNode last) {
		this.last = last;
	}

	@Override
	public String toString() {
		return "Node:  [costs=" + costs + "]";
	}
}

